home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 2: Applications / Linux Cubed Series 2 - Applications.iso / circuits / irsim-ca.2 / irsim-ca / irsim-cap-9.2 / src / irsim / sim.c < prev    next >
C/C++ Source or Header  |  1995-05-26  |  15KB  |  665 lines

  1. /* 
  2.  *     ********************************************************************* 
  3.  *     * Copyright (C) 1988, 1990 Stanford University.                     * 
  4.  *     * Permission to use, copy, modify, and distribute this              * 
  5.  *     * software and its documentation for any purpose and without        * 
  6.  *     * fee is hereby granted, provided that the above copyright          * 
  7.  *     * notice appear in all copies.  Stanford University                 * 
  8.  *     * makes no representations about the suitability of this            * 
  9.  *     * software for any purpose.  It is provided "as is" without         * 
  10.  *     * express or implied warranty.  Export of this software outside     * 
  11.  *     * of the United States of America may require an export license.    * 
  12.  *     ********************************************************************* 
  13.  */
  14.  
  15. /*
  16.  * The routines in this file handle network input (from sim files).
  17.  * The input routine "rd_network" replaces the work formerly done by presim.
  18.  * This version differs from the former in the following:
  19.  *  1. voltage drops across transistors are ignored (assumes transistors
  20.  *     driven by nodes with voltage drops have the same resistance as those
  21.  *     driven by a full swing).
  22.  *  2. static power calculations not performed (only useful for nmos anyhow).
  23.  */
  24.  
  25. #include <stdio.h>
  26. #include "defs.h"
  27. #include "net.h"
  28. #include "globals.h"
  29. #include "net_macros.h"
  30.  
  31.  
  32. #define LSIZE        2000        /* size for input line buffer */
  33. #define    MAXARGS        20        /* max. # of arguments per line */
  34.  
  35.  
  36. public    nptr   VDD_node;        /* power supply nodes */
  37. public    nptr   GND_node;
  38.  
  39. public    lptr   on_trans;        /* always on transistors */
  40.  
  41. public    int    nnodes;            /* number of actual nodes */
  42. public    int    naliases;        /* number of aliased nodes */
  43. public    int    ntrans[ NTTYPES ];    /* number of txtors indexed by type */
  44.  
  45. public    lptr   freeLinks = NULL;    /* free list of Tlist structs */
  46. public    tptr   freeTrans = NULL;    /* free list of Transistor structs */
  47. public    nptr   freeNodes = NULL;    /* free list of Node structs */
  48.  
  49. public    tptr   tcap = NULL;        /* list of capacitor-transistors */
  50.  
  51. private    int    lineno;            /* current input file line number */
  52. private    char   *simfname;        /* current input filename */
  53. private    int    nerrs = 0;        /* # of erros found in sim file */
  54. private    int    isBinFile;        /* TRUE binary file, FALSE sim file */
  55.  
  56. private    tptr   rd_tlist;        /* list of transistors just read */
  57.  
  58. public
  59. #define    MIN_CAP        0.0005        /* minimum node capacitance (in pf) */
  60.  
  61.  
  62. #define    WARNING        0
  63. #define    WARN        1
  64. #define    MAX_ERRS    20
  65. #define    FATAL        (MAX_ERRS + 1)
  66.  
  67. private    char    bad_argc_msg[] = "Wrong number of args for '%c' (%d)\n";
  68.  
  69. #define    BAD_ARGC( CMD, ARGC, ARGV )            \
  70.   {                            \
  71.     error( simfname, lineno, bad_argc_msg, CMD, ARGC );    \
  72.     PrArgs( ARGC, ARGV );                \
  73.     CheckErrs( WARN );                    \
  74.     return;                        \
  75.   }                            \
  76.  
  77.  
  78. private void PrArgs( argc, argv )
  79.   int   argc;
  80.   char  *argv[];
  81.   {
  82.     while( argc-- != 0 )
  83.       (void) fprintf( stderr, "%s ", *argv++ );
  84.     (void) fputs( "\n", stderr );
  85.   }
  86.  
  87.  
  88. private void CheckErrs( n )
  89.   {
  90.     nerrs += n;
  91.     if( nerrs > MAX_ERRS )
  92.       {
  93.     if( n != FATAL )
  94.         (void) fprintf( stderr, "Too many errors in sim file <%s>\n",
  95.           simfname );
  96.     exit( 1 );
  97.       }
  98.   }
  99.  
  100.  
  101.  
  102. /*
  103.  * Traverse the transistor list and add the node connection-list.  We have
  104.  * to be careful with ALIASed nodes.  Note that transistors with source/drain
  105.  * connected VDD and GND nodes are not linked.
  106.  */
  107. private nptr connect_txtors()
  108.   {
  109.     register tptr  t, tnext;
  110.     register nptr  gate, src, drn, nd_list;
  111.     register int   type;
  112.     register long  visited;
  113.  
  114.     visited = VISITED;
  115.     nd_list = NULL;
  116.  
  117.     for( t = rd_tlist; t != NULL; t = tnext )
  118.       {
  119.     tnext = t->scache.t;
  120.     for( gate = t->gate; gate->nflags & ALIAS; gate = gate->nlink);
  121.     for( src = t->source; src->nflags & ALIAS; src = src->nlink );
  122.     for( drn = t->drain; drn->nflags & ALIAS; drn = drn->nlink );
  123.  
  124.     t->gate = gate;
  125.     t->source = src;
  126.     t->drain = drn;
  127.  
  128.     type = t->ttype;
  129.     t->state = ( type & ALWAYSON ) ? WEAK : UNKNOWN;
  130.     t->tflags = 0;
  131.  
  132.     ntrans[ type ]++;
  133.     if( src == drn or (src->nflags & drn->nflags & POWER_RAIL) )
  134.       {
  135.         t->ttype |= TCAP;        /* transistor is just a capacitor */
  136.         LINK_TCAP( t );
  137.       }
  138.     else
  139.       {
  140.         /* do not connect gate if ALWAYSON since they do not matter */
  141.         if( t->ttype & ALWAYSON )
  142.           {
  143.         CONNECT( on_trans, t );
  144.           }
  145.         else
  146.           {
  147.         CONNECT( t->gate->ngate, t );
  148.           }
  149.  
  150.         if( not (src->nflags & POWER_RAIL) )
  151.           {
  152.         CONNECT( src->nterm, t );
  153.         LINK_TO_LIST( src, nd_list, visited );
  154.           }
  155.         if( not (drn->nflags & POWER_RAIL) )
  156.           {
  157.         CONNECT( drn->nterm, t );
  158.         LINK_TO_LIST( drn, nd_list, visited );
  159.           }
  160.       }
  161.       }
  162.  
  163.     return( nd_list );
  164.   }
  165.  
  166.  
  167. /*
  168.  * node area and perimeter info (N sim command).
  169.  */
  170. private void node_info( targc, targv )
  171.   int   targc;
  172.   char  *targv[];
  173.   {
  174.     register nptr  n;
  175.  
  176.     if( targc != 8 )
  177.     BAD_ARGC( 'N', targc, targv );
  178.  
  179.     n = GetNode( targv[1] );
  180.  
  181.     n->ncap +=     atof( targv[4] ) * (CMA * LAMBDA2) +
  182.         atof( targv[5] ) * (CPA * LAMBDA2) +
  183.         atof( targv[6] ) * (CDA * LAMBDA2) +
  184.         atof( targv[7] ) * 2.0 * (CDP * LAMBDA);
  185.   }
  186.  
  187.  
  188. /*
  189.  * new format node area and perimeter info (M sim command).
  190.  */
  191. private void nnode_info( targc, targv )
  192.   int   targc;
  193.   char  *targv[];
  194.   {
  195.     register nptr  n;
  196.  
  197.     if( targc != 14 )
  198.     BAD_ARGC( 'M', targc, targv );
  199.  
  200.     n = GetNode( targv[1] );
  201.  
  202.     n->ncap +=    atof( targv[4] ) * (CM2A * LAMBDA2) +
  203.         atof( targv[5] ) * 2.0 * (CM2P * LAMBDA) +
  204.         atof( targv[6] ) * (CMA * LAMBDA2) +
  205.         atof( targv[7] ) * 2.0 * (CMP * LAMBDA) +
  206.         atof( targv[8] ) * (CPA * LAMBDA2) +
  207.         atof( targv[9] ) * 2.0 * (CPP * LAMBDA) +
  208.         atof( targv[10] ) * (CDA * LAMBDA) +
  209.         atof( targv[11] ) * 2.0 * (CDP * LAMBDA) +
  210.         atof( targv[12] ) * (CPDA * LAMBDA2) +
  211.         atof( targv[13] ) * 2.0 * (CPDP * LAMBDA);
  212.   }
  213.  
  214.  
  215. /*
  216.  * new transistor.  Implant specifies type.
  217.  * AreaPos specifies the argument number that contains the area (if any).
  218.  */
  219. private void newtrans( implant, targc, targv )
  220.   int   implant;
  221.   int   targc;
  222.   char  *targv[];
  223.   {
  224.     nptr           gate, src, drn, ntemp;
  225.     long           x, y, width, length;
  226.     double         cap;
  227.     register tptr  t;
  228.  
  229.     if( implant == RESIST )
  230.       {
  231.     if( targc != 4 )
  232.         BAD_ARGC( 'r', targc, targv );
  233.  
  234.     gate = VDD_node;
  235.     src = GetNode( targv[1] );
  236.     drn = GetNode( targv[2] );
  237.  
  238.     length = atof( targv[3] ) * LAMBDACM;
  239.     width = 0;
  240.       }
  241.     else
  242.       {
  243.     if( targc < 4 or targc > 11 )
  244.         BAD_ARGC( targv[0][0], targc, targv );
  245.  
  246.     gate = GetNode( targv[1] );
  247.     src = GetNode( targv[2] );
  248.     drn = GetNode( targv[3] );
  249.  
  250.     if( targc > 5 )
  251.       {
  252.         length = atof( targv[4] ) * LAMBDACM;
  253.         width = atof( targv[5] ) * LAMBDACM;
  254.         if( width <= 0 or length <= 0 )
  255.           {
  256.         error( simfname, lineno,
  257.           "Bad transistor width=%g or length=%g\n", width, length );
  258.         return;
  259.           }
  260.         if( targc > 7 )
  261.           {
  262.         x = atoi( targv[6] );
  263.         y = atoi( targv[7] );
  264.           }
  265.       }
  266.     else
  267.         width = length = 2 * LAMBDACM;
  268.  
  269.     cap = length * width * CTGA;
  270.       }
  271.  
  272.     NEW_TRANS( t );            /* create new transistor */
  273.  
  274.     t->ttype = implant;
  275.     t->gate = gate;
  276.     t->source = src;
  277.     t->drain = drn;
  278.  
  279.     if( targc > 7 )
  280.       {
  281.     t->x.pos = x;
  282.     t->y.pos = y;
  283.     EnterPos( t, TRUE );        /* Enter transistor position */
  284.       }
  285.     else
  286.     EnterPos( t, FALSE );        /* Enter transistor position */
  287.  
  288.     t->scache.t = rd_tlist;        /* link it to the list */
  289.     rd_tlist = t;
  290.  
  291.     t->r = requiv( implant, width, length );
  292.  
  293.         /* update node capacitances  */
  294.     gate->ncap += cap;
  295.  
  296.     if( config_flags & TDIFFCAP )
  297.       {
  298.     cap = CTDW * width + CTDE;
  299.     src->ncap += cap;
  300.     drn->ncap += cap;
  301.       }
  302.   }
  303.         
  304.  
  305. /*
  306.  * accept a bunch of aliases for a node (= sim command).
  307.  */
  308. private void alias( targc, targv )
  309.   int   targc;
  310.   char  *targv[];
  311.   {
  312.     register nptr  n, m;
  313.     register int   i;
  314.  
  315.     if( targc < 3 )
  316.     BAD_ARGC( '=', targc, targv );
  317.  
  318.     n = GetNode( targv[1] );
  319.  
  320.     for( i = 2; i < targc; i++ )
  321.       {
  322.     m = GetNode( targv[i] );
  323.     if( m == n )
  324.         continue;
  325.  
  326.     if( m->nflags & POWER_RAIL )
  327.         SWAP_NODES( m, n );
  328.  
  329.     if( m->nflags & POWER_RAIL )
  330.       {
  331.         error( simfname, lineno, "Can't alias the power supplies\n" );
  332.         continue;
  333.       }
  334.  
  335.     n->ncap += m->ncap;
  336.     n->naliases += m->naliases + 1;        /* (PEL 5/28/93) */
  337.  
  338.     m->nlink = n;
  339.     m->nflags |= ALIAS;
  340.     m->ncap = 0.0;
  341.     m->naliases = 0;            /* (PEL 5/28/93) */
  342.     nnodes--;
  343.     naliases++;
  344.       }
  345.   }
  346.  
  347.  
  348. /*
  349.  * node threshold voltages (t sim command).
  350.  */
  351. private void nthresh( targc, targv )
  352.   int   targc;
  353.   char  *targv[];
  354.   {
  355.     register nptr  n;
  356.  
  357.     if( targc != 4 )
  358.     BAD_ARGC( 't', targc, targv );
  359.  
  360.     n = GetNode( targv[1] );
  361.     n->vlow = atof( targv[2] );
  362.     n->vhigh = atof( targv[3] );
  363.   }
  364.  
  365.  
  366. /*
  367.  * User delay for a node (D sim command).
  368.  */
  369. private void ndelay( targc, targv )
  370.   int   targc;
  371.   char  *targv[];
  372.   {
  373.     register nptr  n;
  374.  
  375.     if( targc != 4 )
  376.     BAD_ARGC( 'D', targc, targv );
  377.  
  378.     n = GetNode( targv[1] );
  379.     n->nflags |= USERDELAY;
  380.     n->tplh = ns2d( atof( targv[2] ) );
  381.     n->tphl = ns2d( atof( targv[3] ) );
  382.   }
  383.  
  384.  
  385. /*
  386.  * add capacitance to a node (c sim command).
  387.  */
  388. private void ncap( targc, targv )
  389.   int   targc;
  390.   char  *targv[];
  391.   {
  392.     register nptr n, m;
  393.     float         cap;
  394.  
  395.     if( targc == 3 )
  396.       {
  397.     n = GetNode( targv[1] );
  398.     n->ncap += atof( targv[2] );
  399.       }
  400.     else if( targc == 4 )        /* two terminal caps    */
  401.       {
  402.     cap = atof( targv[3] ) / 1000;        /* ff to pf conversion */
  403.     n = GetNode( targv[1] );
  404.     m = GetNode( targv[2] );
  405.     if( n != m )            /* add cap to both nodes */
  406.       {
  407.         if( m != GND_node )    m->ncap += cap;
  408.         if( n != GND_node )    n->ncap += cap;
  409.       }
  410.     else if( n == GND_node )    /* same node, only GND makes sense */
  411.         n->ncap += cap;
  412.       }
  413.     else
  414.     BAD_ARGC( 'c', targc, targv );
  415.   }
  416.  
  417.  
  418. /*
  419.  * parse input line into tokens, filling up carg and setting targc
  420.  */
  421. private int parse_line( line, carg )
  422.   register char  *line;
  423.   register char  **carg;
  424.   {
  425.     register char  ch;
  426.     register int   targc;
  427.  
  428.     targc = 0;
  429.     while( ch = *line++ )
  430.       {
  431.     if( ch <= ' ' )
  432.         continue;
  433.     targc++;
  434.     *carg++ = line - 1;
  435.     while( *line > ' ' )
  436.         line++;
  437.     if( *line )
  438.         *line++ = '\0';
  439.       }
  440.     *carg = 0;
  441.     return( targc );
  442.   }
  443.  
  444.  
  445. private    int    R_error = FALSE;
  446. private    int    A_error = FALSE;
  447.  
  448.  
  449. private int input_sim( simfile )
  450.   char  *simfile;
  451.   {
  452.     FILE  *fin;
  453.     char  line[LSIZE];
  454.     char  *targv[MAXARGS];    /* tokens on current command line */
  455.     int   targc;        /* number of args on command line */
  456.     long  offset;        /* state of previously opened file */
  457.     int   olineno;
  458.  
  459.     if( (fin = fopen( simfile, "r" )) == NULL )
  460.       {
  461.     lprintf( stderr, "cannot open '%s' for sim input\n", simfile );
  462.     return( FALSE );
  463.       }
  464.     simfname = simfile;
  465.     lineno = 0;
  466.  
  467.     while( fgetline( line, LSIZE, fin ) != NULL )
  468.       {
  469.     lineno++;
  470.     targc = parse_line( line, targv );
  471.     if( targv[0] == NULL )
  472.         continue;
  473.     switch( targv[0][0] )
  474.       {
  475.         case '@' :
  476.         if( targc != 2 )
  477.           {
  478.             error( simfname, lineno, bad_argc_msg, '@', targc );
  479.             CheckErrs( WARN );
  480.             break;
  481.           }
  482.         offset = ftell( fin );
  483.         olineno = lineno;
  484.         (void) fclose( fin );
  485.         (void) input_sim( targv[1] );
  486.         if( (fin = fopen( simfile, "r" )) == NULL )
  487.           {
  488.             error( simfname, lineno, "can't re-open sim file '%s'\n",
  489.                simfile );
  490.             CheckErrs( WARN );
  491.             return( FALSE );
  492.           }
  493.         (void) fseek( fin, offset, 0 );
  494.         simfname = simfile;
  495.         lineno = olineno;
  496.         break;
  497.  
  498.         case '|' :
  499.         break;
  500.         case 'e' :
  501.         case 'n' :
  502.         newtrans( NCHAN, targc, targv );
  503.         break;
  504.         case 'p' :
  505.         newtrans( PCHAN, targc, targv );
  506.         break;
  507.         case 'd' :
  508.         newtrans( DEP, targc, targv );
  509.         break;
  510.         case 'r' :
  511.         newtrans( RESIST, targc, targv );
  512.         break;
  513.         case 'N' :
  514.         node_info( targc, targv );
  515.         break;
  516.         case 'M' :
  517.         nnode_info( targc, targv );
  518.         break;
  519.         case 'c' :
  520.         case 'C' :
  521.             ncap( targc, targv );
  522.         break;
  523.         case '=' :
  524.             alias( targc, targv );
  525.         break;
  526.         case 't' :
  527.             nthresh( targc, targv );
  528.         break;
  529.         case 'D' : 
  530.             ndelay( targc, targv );
  531.         break;
  532.         case 'R' : 
  533.         if( not R_error )    /* only warn about this 1 time */
  534.           {
  535.             lprintf( stderr,
  536.               "%s: Ignoring lumped-resistance ('R' construct)\n",
  537.               simfname );
  538.             R_error = TRUE;
  539.           }
  540.         break;
  541.         case 'A' :
  542.         if( not A_error )    /* only warn about this 1 time */
  543.           {
  544.             lprintf( stderr,
  545.               "%s: Ignoring attribute-line ('A' construct)\n",
  546.               simfname );
  547.             A_error = TRUE;
  548.           }
  549.         break;
  550.         case '<' : 
  551.         if( lineno == 1 and rd_netfile( fin, line ) )
  552.           {
  553.             (void) fclose( fin );
  554.             return( TRUE );
  555.           }
  556.         /* fall through if rd_netfile returns FALSE */
  557.         default :
  558.         error( simfname, lineno, "Unrecognized input line (%s)\n",
  559.           targv[0] );
  560.         CheckErrs( WARN );
  561.       }
  562.       }
  563.     (void) fclose( fin );
  564.     return( FALSE );
  565.   }
  566.  
  567.  
  568.  
  569. private void init_counts()
  570.   {
  571.     register int  i;
  572.  
  573.     for( i = 0; i < NTTYPES; i++ )
  574.     ntrans[i] = 0;
  575.     nnodes = naliases = 0;
  576.   }
  577.  
  578.  
  579. public int rd_network( simfile )
  580.   char  *simfile;
  581.   {
  582.     static int      firstcall = 1;
  583.  
  584.     if( firstcall )
  585.       {
  586.     rd_tlist = NULL;
  587.     init_hash();
  588.     init_counts();
  589.     init_listTbl();
  590.  
  591.     VDD_node = GetNode( "Vdd" );
  592.     VDD_node->npot = HIGH;
  593.     VDD_node->nflags |= (INPUT | POWER_RAIL);
  594.     VDD_node->head.inp = 1;
  595.     VDD_node->head.val = HIGH;
  596.     VDD_node->head.punt = 0;
  597.     VDD_node->head.time = 0;
  598.     VDD_node->head.t.r.rtime = VDD_node->head.t.r.delay = 0;
  599.     VDD_node->head.next = last_hist;
  600.     VDD_node->curr = &(VDD_node->head);
  601.  
  602.     GND_node = GetNode( "Gnd" );
  603.     GND_node->npot = LOW;
  604.     GND_node->nflags |= (INPUT | POWER_RAIL);
  605.     GND_node->head.inp = 1;
  606.     GND_node->head.val = LOW;
  607.     GND_node->head.punt = 0;
  608.     GND_node->head.time = 0;
  609.     GND_node->head.t.r.rtime = GND_node->head.t.r.delay = 0;
  610.     GND_node->head.next = last_hist;
  611.     GND_node->curr = &(GND_node->head);
  612.  
  613.     NEW_TRANS( tcap );
  614.     tcap->scache.t = tcap->dcache.t = tcap;
  615.     tcap->x.pos = 0;
  616.  
  617.     firstcall = 0;
  618.       }
  619.     nerrs = 0;
  620.  
  621.     isBinFile = input_sim( simfile );
  622.     if( nerrs > 0 )
  623.     exit( 1 );
  624.   }
  625.  
  626.  
  627. public void pTotalNodes()
  628.   {
  629.     lprintf( stdout, "%d nodes", nnodes );
  630.     if( naliases != 0 )
  631.     lprintf( stdout, ", %d aliases", naliases );
  632.     lprintf( stdout, "; " );
  633.   }
  634.  
  635.  
  636. public void pTotalTxtors()
  637.   {
  638.     int  i;
  639.  
  640.     lprintf( stdout, "transistors:" );
  641.     for( i = 0; i < NTTYPES; i++ )
  642.     if( ntrans[i] != 0 )
  643.         lprintf( stdout, " %s=%d", ttype[i], ntrans[i] );
  644.     if( tcap->x.pos != 0 )
  645.     lprintf( stdout, " shorted=%d", tcap->x.pos );
  646.     lprintf( stdout, "\n" );
  647.   }
  648.  
  649.  
  650. public void ConnectNetwork()
  651.   {
  652.     nptr  ndlist;
  653.  
  654.     pTotalNodes();
  655.  
  656.     ndlist = ( isBinFile ) ? bin_connect_txtors() : connect_txtors();
  657.  
  658.     make_parallel( ndlist );
  659.     make_stacks( ndlist );
  660.  
  661.     pTotalTxtors();
  662.     pParallelTxtors();
  663.     pStackedTxtors();
  664.   }
  665.